package at.kokoni.Koko_Ni.util;

import android.app.AlertDialog;
import android.os.AsyncTask;
import android.util.Log;
import at.kokoni.Koko_Ni.entities.ApiResponse;
import at.kokoni.Koko_Ni.entities.Post;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutionException;

public class PostUtil extends AsyncTask<Object, Void, Post[]> {
	private static List<Post> loadedPosts = new LinkedList<Post>();

	@Override
	protected Post[] doInBackground(Object... params) {
		if (params[0] instanceof String) {
			String func = (String) params[0];
			if (func.equalsIgnoreCase("post.coordinates")) {
				if (params[1] instanceof LatLngBounds) {
					return getPostByArea((LatLngBounds) params[1]);
				} else {
					Log.e("Post", "Parameter LatLngBounds");
				}
			} else if (func.equalsIgnoreCase("post.id")) {
				if (params[1] instanceof Integer) {
					return new Post[]{getPostById((Integer) params[1])};
				} else {
					Log.e("Post", "Parameter not Integer");
				}
			} else if (func.equalsIgnoreCase("post.create")) {
				if (params[1] instanceof String && params[2] instanceof LatLng && params[3] instanceof String && (params[4] == null || params[4] instanceof String)) {
					post((String) params[1], (LatLng) params[2], (String) params[3], (String) params[4]);
					return null;
				} else {
					Log.e("Post", "Parameter not correct");
				}
			}
		}
		return null;
	}

	private static Post getPostById(int id) throws IllegalArgumentException {
		if (id <= 0) throw new IllegalArgumentException("Id must be > 0");
		Post p;
		p = contains(id);
		if (p != null) return p;

		UrlBuilder builder = new UrlBuilder("https://BASEURL/post/id/" + id);
		RestUtil util = new RestUtil(builder.getUrl());
		String json = util.get();
		if (json == null) {
			Log.w("Post.getPostById", "No internet connection");
			return null;
		}
		ApiResponse response = ApiResponse.responseFromJson(json);
		if (response.getReturnValue() == 0) {
			Post tmp = Post.postFromJson(response.getDataValue());
			tmp.setId(id);
			loadedPosts.add(tmp);
			return tmp;
		} else {
			return null;
		}

	}

	private static Post[] getPostByArea(LatLngBounds bounds) {
		return getPostByArea(bounds.northeast.latitude, bounds.northeast.longitude, bounds.southwest.latitude, bounds.southwest.longitude);
	}

	private static Post[] getPostByArea(double latnortheast, double longnortheast, double latsouthwest, double longsouthwest) {

		UrlBuilder builder = new UrlBuilder(String.format((Locale) null, "https://BASEURL/post/coordinates/%f/%f/%f/%f", latnortheast, longnortheast, latsouthwest, longsouthwest));
		RestUtil util = new RestUtil(builder.getUrl());
		String json = util.get();
		if (json == null) {
			Log.w("Post.getPostByArea", "No internet connection");
			return null;
		}
		ApiResponse response = ApiResponse.responseFromJson(json);
		if (response.getReturnValue() == 0) {
			JsonParser parser = new JsonParser();
			JsonArray array = parser.parse(response.getDataValue()).getAsJsonArray();
			List<Post> posts = new LinkedList<Post>();
			for (JsonElement jid : array) {
				int id = jid.getAsInt();
				Post tmp = getPostById(id);

				if (tmp != null) posts.add(tmp);
				else Log.wtf("Post", "Post not found"); // impossible condition
			}
			return posts.toArray(new Post[posts.size()]);
		}
		return null;
	}

	private static void post(String text, LatLng latLng, String session, String image) {
		Post post = new Post(text, latLng.latitude, latLng.longitude);
		try {
			new AsyncLayer() {
			}.execute("post", "https://BASEURL/post/create", post, session, image);
		} catch (Exception e) {

		}
	}

	private static Post contains(int id) {
		for (Post p : loadedPosts) {
			if (p.getId() == id) {
				return p;
			}
		}
		return null;
	}

}
